package main

import (
	"database/sql"
	"encoding/json"
	"reflect"

	"test.com/fusion"
	"test.com/worlddb"
)

type itemDialogTableRow struct {
	ItemTypeID uint32 `json:"itemTypeID"`
	ItemName   string `json:"itemName"`
	ItemDesc   string `json:"itemDesc"`
}

func getAllItem4DialogTable(db *sql.DB) ([]*itemDialogTableRow, error) {
	itemNames, err := getAllKeyI18Ns(db,
		"item_prototype", "itemTypeID", worlddb.STRING_TEXT_TYPE_ITEM_NAME)
	if err != nil {
		return nil, err
	}
	itemDescs, err := getAllKeyI18Ns(db,
		"item_prototype", "itemTypeID", worlddb.STRING_TEXT_TYPE_ITEM_DESC)
	if err != nil {
		return nil, err
	}
	var itemRows []*itemDialogTableRow
	for itemID, itemName := range itemNames {
		itemDesc := itemDescs[itemID]
		itemRows = append(itemRows,
			&itemDialogTableRow{itemID, itemName, itemDesc})
	}
	return itemRows, nil
}

func getAllItemNames(db *sql.DB) (map[uint32]string, error) {
	return getAllKeyI18Ns(db,
		"item_prototype", "itemTypeID", worlddb.STRING_TEXT_TYPE_ITEM_NAME)
}

func getAllItemClasses(db *sql.DB) (map[uint32][]int, error) {
	var itemClasses = map[uint32][]int{}
	rows, err := db.Query(
		"SELECT `itemTypeID`,`itemClass`,`itemSubClass` FROM `item_prototype`")
	if err != nil {
		return nil, err
	}
	defer rows.Close()
	for rows.Next() {
		var itemTypeID uint32
		var itemClass, itemSubClass int
		if err := rows.Scan(&itemTypeID, &itemClass, &itemSubClass); err == nil {
			itemClasses[itemTypeID] = []int{itemClass, itemSubClass}
		} else {
			return nil, err
		}
	}
	return itemClasses, nil
}

func getItemInfo(db *sql.DB, itemTypeID uint32) (*worlddb.ItemPrototype, error) {
	var itemInfo *worlddb.ItemPrototype
	itemInfoVals, err := fusion.LoadJsontableFromDB(
		db, reflect.TypeOf(itemInfo), "`itemTypeID`=?", itemTypeID)
	if err != nil {
		return nil, err
	}
	if itemInfoVals.Len() < 1 {
		return nil, sql.ErrNoRows
	}
	return itemInfoVals.Index(0).Interface().(*worlddb.ItemPrototype), nil
}

func getItemInstanceJsonData(db *sql.DB, itemTypeID uint32) ([]byte, error) {
	var err error
	var itemProto itemWebPrototype
	itemProto.ItemName, err =
		getI18N(db, worlddb.STRING_TEXT_TYPE_ITEM_NAME, itemTypeID)
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}
	itemProto.ItemDesc, err =
		getI18N(db, worlddb.STRING_TEXT_TYPE_ITEM_DESC, itemTypeID)
	if err != nil && err != sql.ErrNoRows {
		return nil, err
	}
	itemProto.ItemInfo, err = getItemInfo(db, itemTypeID)
	if err != nil {
		return nil, err
	}
	itemData, err := json.Marshal(
		fusion.MarshalEntityToInterface(&itemProto, "json"))
	if err != nil {
		return nil, err
	}
	return itemData, nil
}

func newItemInstance(tx *sql.Tx, itemName, itemDesc string) (uint32, error) {
	itemInfo := worlddb.ItemPrototype{}
	itemTypeID, err := fusion.SaveJsontableToDB(tx, &itemInfo)
	if err != nil {
		return 0, err
	}
	err = setI18Ns(tx,
		worlddb.STRING_TEXT_TYPE_ITEM_NAME, itemTypeID, itemName,
		worlddb.STRING_TEXT_TYPE_ITEM_DESC, itemTypeID, itemDesc)
	if err != nil {
		return 0, err
	}
	return itemTypeID, nil
}

func copyItemInstance(db *sql.DB, tx *sql.Tx, itemTypeID uint32) (uint32, error) {
	var itemInfo *worlddb.ItemPrototype
	itemInfoVals, err := fusion.LoadJsontableFromDB(
		db, reflect.TypeOf(itemInfo), "`itemTypeID`=?", itemTypeID)
	if err != nil {
		return 0, err
	}
	if itemInfoVals.Len() < 1 {
		return 0, sql.ErrNoRows
	}
	itemInfo = itemInfoVals.Index(0).Interface().(*worlddb.ItemPrototype)
	itemInfo.ItemTypeID = 0
	ID, err := fusion.SaveJsontableToDB(tx, itemInfo)
	if err != nil {
		return 0, err
	}
	err = copyI18Ns(db, tx,
		worlddb.STRING_TEXT_TYPE_ITEM_NAME, itemTypeID, ID,
		worlddb.STRING_TEXT_TYPE_ITEM_DESC, itemTypeID, ID)
	if err != nil {
		return 0, err
	}
	return ID, nil
}

func deleteItemInstance(tx *sql.Tx, itemTypeID uint32) error {
	_, err := tx.Exec(
		"DELETE FROM `item_prototype` WHERE `itemTypeID`=?", itemTypeID)
	if err != nil {
		return err
	}
	return nil
}

func saveItemInstance(tx *sql.Tx, itemProto *ItemPrototype) error {
	err := setI18Ns(tx,
		worlddb.STRING_TEXT_TYPE_ITEM_NAME,
		itemProto.ItemInfo.ItemTypeID, itemProto.ItemName,
		worlddb.STRING_TEXT_TYPE_ITEM_DESC,
		itemProto.ItemInfo.ItemTypeID, itemProto.ItemDesc)
	if err != nil {
		return err
	}
	_, err = fusion.SaveJsontableToDB(tx, itemProto.ItemInfo)
	if err != nil {
		return err
	}
	return nil
}
